package com.ikingtech.framework.sdk.authenticate.embedded.authenticate;

import com.ikingtech.framework.sdk.authenticate.embedded.core.Credential;
import com.ikingtech.framework.sdk.authenticate.embedded.core.UserIdentityLoader;
import com.ikingtech.framework.sdk.authenticate.extension.IdentityExtensionLoader;
import com.ikingtech.framework.sdk.cache.constants.CacheConstants;
import com.ikingtech.framework.sdk.context.security.Identity;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.enums.authenticate.SignEndpointTypeEnum;
import com.ikingtech.framework.sdk.utils.Tools;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author tie yan
 */
public class SocialAuthenticate extends AbstractAuthenticate {

    private final UserIdentityLoader userIdentityLoader;

    public SocialAuthenticate(StringRedisTemplate redisTemplate, List<IdentityExtensionLoader> loaders, UserIdentityLoader userIdentityLoader) {
        super(redisTemplate, loaders);
        this.userIdentityLoader = userIdentityLoader;
    }

    @Override
    public Identity doVerify(Credential credential, String token) {
        Identity result = this.userIdentityLoader.loadBySocial(credential.getSocialId(), credential.getSocialNo());
        if (result == null) {
            throw new FrameworkException("userNotFound");
        }

        this.resolveMultiSign(result.getId(), Me.tenantCode());
        // 设置用户当前登录端点
        result.setEndpoint(null == credential.getEndpointType() ? SignEndpointTypeEnum.PC.name() : credential.getEndpointType().name());

        List<String> tokens = new ArrayList<>();
        if (SignEndpointTypeEnum.WECHAT_MINI.equals(credential.getEndpointType())) {
            // 获取当前用户在小程序端的所有已登录的token
            tokens.addAll(Objects.requireNonNull(this.redisTemplate.opsForList().range(CacheConstants.loginUserFormat(result.getId(), credential.getEndpointType().name()), 0, -1)));
        }
        result.setToken(Tools.Coll.isBlank(tokens) ? token : tokens.get(0));

        return result;
    }

    @Override
    public Boolean support(Credential credential) {
        return Tools.Str.isNotBlank(credential.getSocialNo()) && Tools.Str.isNotBlank(credential.getSocialId());
    }
}
